package forum.client;

import java.util.Date;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.datepicker.client.DatePicker;
import forum.shared.*;

public class RegisterScreen extends Screen {
	private Label title;
	private Label note;
	private TextBox username;
	private Label usernameLabel;
	private PopupPanel popupPanel;
	private TextBox firstName;
	private Label firstNameLabel;
	private TextBox lastName;
	private Label lastNameLabel;
	private TextBox email;
	private Label emailLabel;
	private TextBox city;
	private Label cityLabel;
	private DatePicker dob;
	private Label dobLabel;
	private RadioButton male;
	private RadioButton female;
	private Label genderLabel;
	private FlowPanel genderChoisePanel;
	private TextBox dateChosen;
	private TextBox password;
	private Label passwordLabel;
	private TextBox confirmPassword;
	private Label confirmPasswordLabel;
	private Label errorLbl;
	private Button register;
	private Button cancel;
	
	private FlexTable mainTable;
	private FlexTable buttonsTable;
	private HorizontalPanel contentPanel;
	
	/**
	 * default constructor.
	 */
	public RegisterScreen(){
		createComponents();
		setStyle();
		setTabOrder();
		setActions();
		setupScreenDisplay();
	}
	
	/**
	 * init all the components.
	 */
	protected void createComponents(){
		title = new Label("Bannana Forum Registration");
		note = new Label("Fields marked with * are mandatory");
		username = new TextBox();
		usernameLabel = new Label("*Username:");
		popupPanel = new PopupPanel(true);
		firstName = new TextBox();
		firstNameLabel = new Label("First Name:");
		lastName = new TextBox();
		lastNameLabel = new Label("Last Name:");
		email = new TextBox();
		emailLabel = new Label("E-Mail:");
		city = new TextBox();
		cityLabel = new Label("City:");
		dob = new DatePicker();
		dobLabel = new Label("Date Of Birth:");
		male = new RadioButton("gender", "Male");
		female = new RadioButton("gender", "Female");
		genderLabel = new Label("Gender:");
		genderChoisePanel=new FlowPanel();
		dateChosen = new TextBox();
		password = new PasswordTextBox();
		passwordLabel = new Label("*Password:");
		confirmPassword = new PasswordTextBox();
		confirmPasswordLabel = new Label("*Confirm Password:");
		register = new Button("Register");
		cancel = new Button("Cancel");
		mainTable = new FlexTable();
		buttonsTable = new FlexTable();
		contentPanel = new HorizontalPanel();
		// Set the default value
	    dob.setValue(new Date(), true);
	    // Move cursor focus to the input box.
	    username.setFocus(true);
	    errorLbl = new Label();
	}
	
	/**
	 * setting the style to all the components.
	 */
	protected void setStyle(){
		errorLbl.addStyleName("errorLabel");
		errorLbl.setHorizontalAlignment(HasAlignment.ALIGN_CENTER);
		errorLbl.setVisible(false);
		mainTable.addStyleName("blueStyleTable");
		buttonsTable.addStyleName("buttonsTableCenter");
		contentPanel.addStyleName("horizontalPanel");
		note.setStyleName("notes");
		title.addStyleName("title");
		mainTable.setSize("100%", "100%");
		int rows=8;
		for(int row=0;row<rows;row++){
			for(int col=0;col<=1;col++){
				mainTable.getCellFormatter().setStyleName(row, col, "blueStyleTd");
				if(col==0)
					mainTable.getCellFormatter().setHorizontalAlignment(row, col, HasAlignment.ALIGN_LEFT);
				else
					mainTable.getCellFormatter().setHorizontalAlignment(row, col, HasAlignment.ALIGN_CENTER);
			}
		}
		buttonsTable.getCellFormatter().setHorizontalAlignment(0, 0, HasAlignment.ALIGN_RIGHT);
		buttonsTable.getCellFormatter().setHorizontalAlignment(0, 1, HasAlignment.ALIGN_LEFT);
		//setting the style to the fields.
		username.addStyleName("fieldcell");
		password.addStyleName("fieldcell");
		confirmPassword.addStyleName("fieldcell");
		firstName.addStyleName("fieldcell");
		lastName.addStyleName("fieldcell");
		email.addStyleName("fieldcell");
		city.addStyleName("fieldcell");
		dateChosen.setStyleName("fieldcell");
		genderChoisePanel.addStyleName("fieldcell");
		//Setting the style to the labels.
		usernameLabel.addStyleName("labelcell");
		passwordLabel.addStyleName("labelcell");
		confirmPasswordLabel.addStyleName("labelcell");
		firstNameLabel.addStyleName("labelcell");
		lastNameLabel.addStyleName("labelcell");
		emailLabel.addStyleName("labelcell");
		cityLabel.addStyleName("labelcell");
		dobLabel.addStyleName("labelcell");
		genderLabel.addStyleName("labelcell");
		//setting the buttons style.
		register.addStyleName("button");
		cancel.addStyleName("button");
	}
	
	protected void setTabOrder(){
		username.setTabIndex(1);
		password.setTabIndex(2);
		confirmPassword.setTabIndex(2);
		firstName.setTabIndex(3);
		lastName.setTabIndex(4);
		email.setTabIndex(5);
		city.setTabIndex(6);
		male.setTabIndex(8);
		female.setTabIndex(9);
	}
	
	/**
	 * setting all the action for the buttons and mouse clicks.
	 */
	protected void setActions(){
		dateChosen.addClickHandler(new ClickHandler() {
	    	 public void onClick(ClickEvent event) {
		    	 popupPanel.setPopupPosition(dateChosen.getAbsoluteLeft(), dateChosen.getAbsoluteTop() + dateChosen.getOffsetHeight());
		    	 popupPanel.show();
	    	 }
	    });
	    female.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_TAB || event.getCharCode() == KeyCodes.KEY_ENTER) {
					female.setValue(true);
					male.setValue(false);
					popupPanel.setPopupPosition(dateChosen.getAbsoluteLeft(), dateChosen.getAbsoluteTop() + dateChosen.getOffsetHeight());
			    	popupPanel.show();
			    }
			}
		}); 
	    male.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(KeyPressEvent event) {
				
				if (event.getCharCode() == KeyCodes.KEY_ENTER) {
					female.setValue(false);
					male.setValue(true);
					popupPanel.setPopupPosition(dateChosen.getAbsoluteLeft(), dateChosen.getAbsoluteTop() + dateChosen.getOffsetHeight());
			    	popupPanel.show();
			    }
			}
		});
	    // Listen for mouse events on the cancel button.
	    cancel.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				new MainScreen().setupDisplayInMainPanel();
			}
		});
	    // Listen for mouse events on the register button.
	    register.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				register();
			}
		});
	    // Listen for keyboard events on the register button.
	    register.addKeyPressHandler(new KeyPressHandler() {
			
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_ENTER) {
					register();
			    }
			}
		}); 
	    // Set the value in the text box when the user selects a date
	    dob.addValueChangeHandler(new ValueChangeHandler<Date>() {
			@Override
			public void onValueChange(ValueChangeEvent<Date> event) {
				Date date = event.getValue();
		        String dateString = DateTimeFormat.getMediumDateFormat().format(date);
		        dateChosen.setText(dateString);
		        popupPanel.hide();
			}
		});

	}
	
	/**
	 * @return the data to send to the server.
	 */
	protected String getInput(){
		String usernameStr = username.getText();
		String passStr = password.getText();
		String confirmPassStr = confirmPassword.getText();
		String error = "";
		String d = Delimiters.MSG_PARTS;
		
        if (usernameStr.length()<6) {
            error+="- username should be at least 6 characters long.\n";
        }
        if (passStr.length()==0) {
            error+="- Please choose a password\n";
        } else if (!confirmPassStr.equals(passStr)) {
            error+="- Password and password-confirmation do not match.\n";
        }
        if (!error.equals("")) {
        	errorLbl.setText(error);
        	errorLbl.setVisible(true);
  	      	return null;
        }
        // if successful:
        
        String firstName = this.firstName.getText();
        String lastName = this.lastName.getText();
        String email = this.email.getText();
        String gender=null;
        if (male.getValue())
            gender = "MALE";
        else 
            gender = "FEMALE";
        String city = this.city.getText();
        String birthday=dateChosen.getText();
        return "Register" + d + usernameStr + d + passStr+ d + firstName + 
        d + lastName + d + email + d + gender + d + city + d + birthday;
	}
	
	/**
	 * the function to do when registering.
	 */
	private void register(){
		register.setEnabled(false);
		ForumServiceAsync forumSvc = GWT.create(ForumService.class);
		// Set up the callback object.
	    AsyncCallback<ServerResponse> callback = new AsyncCallback<ServerResponse>() {
	    	public void onFailure(Throwable caught) {
	    		errorLbl.setText("Communication error. Please retry later.");
	    		errorLbl.setVisible(true);
	    		register.setEnabled(true);
	    	}
	    	//On successful communication.
			@Override
			public void onSuccess(ServerResponse response) {
				if (response!=null && response.hasExecuted()) {
					username.setText("");
					password.setText("");
					confirmPassword.setText("");
					firstName.setText("");
					lastName.setText("");
					email.setText("");
					city.setText("");
					male.setValue(true);
					female.setValue(false);
					Window.alert(response.getResponse());
					register.setEnabled(true);
					errorLbl.setVisible(false);
					new MainScreen().setupDisplayInMainPanel();
	            } 
				else {
					errorLbl.setText(response!=null ? 
                			response.getResponse() : "Unknown Error...");
                	errorLbl.setVisible(true);
	            }
			}
	    };
		// Make the call to the forum service.
	    String input = getInput();
	    if(input == null) {
	    	register.setEnabled(true);
	    	return;
	    }
	    forumSvc.sendMsg(input, callback);
	}
	
	
	/**
	 * composing the screen on top of the mainPanel which controls the body of the html.
	 */
	public void setupDisplayInMainPanel() {
		Panel mainPanel = MainPanel.get();
		mainPanel.clear();
		//mainPanel.add(time);
		mainPanel.add(title);
		mainPanel.add(contentPanel);
		mainPanel.add(errorLbl);
		mainPanel.add(buttonsTable);
		mainPanel.add(note);
	}
	
	/**
	 * setting up the display of this screen.
	 */
	protected void setupScreenDisplay(){
		contentPanel.add(mainTable);
		popupPanel.add(dob);
		genderChoisePanel.add(male);
		genderChoisePanel.add(female);
		mainTable.setWidget(0, 0, usernameLabel);
		mainTable.setWidget(0, 1, username);
		mainTable.setWidget(1, 0, passwordLabel);
		mainTable.setWidget(1, 1, password);
		mainTable.setWidget(2, 0, confirmPasswordLabel);
		mainTable.setWidget(2, 1, confirmPassword);
		mainTable.setWidget(3, 0, firstNameLabel);
		mainTable.setWidget(3, 1, firstName);
		mainTable.setWidget(4, 0, lastNameLabel);
		mainTable.setWidget(4, 1, lastName);
		mainTable.setWidget(5, 0, emailLabel);
		mainTable.setWidget(5, 1, email);
		mainTable.setWidget(6, 0, cityLabel);
		mainTable.setWidget(6, 1, city);
		mainTable.setWidget(7, 0, genderLabel);
		mainTable.setWidget(7, 1, genderChoisePanel);
		//mainTable.setWidget(8, 0, dobLabel);
		//mainTable.setWidget(8, 1, dateChosen);
		
		buttonsTable.setWidget(0, 0, register);
		buttonsTable.setWidget(0, 1, cancel);
	}
}
